// TODO: Improve documnetation
//! Impls [`Channel`] trait for all pins.

use core::convert::TryFrom;

use crate::gpio::{self, Analog};
use crate::hal::adc::Channel;
use crate::pac;

macro_rules! channel {
    ([$(($Pin:ident, [$(($ADC:ident, $chan:expr)),+])),+ $(,)*]) => {
        $($(
            impl Channel<pac::$ADC> for gpio::$Pin<Analog> {
                type ID = Id;
                fn channel() -> Self::ID { $chan }
            }

            impl Channel<pac::$ADC> for &gpio::$Pin<Analog> {
                type ID = Id;
                fn channel() -> Self::ID { $chan }
            }
        )+)+
    };
}

/// The channel id associated to a gpio pin, with which the ADC peripheral is
/// configured.
///
/// To get the corresponding channel Id, use `Pin::channel()` throgh the
/// [`embedded_hal::adc::Channel`] trait.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Id {
    /// 0
    // FIXME: Can not configure on feature, because 0 is the reset value.
    #[cfg(feature = "stm32f373")]
    Zero,
    /// 1
    One,
    /// 2
    Two,
    /// 3
    Three,
    /// 4
    Four,
    /// 5
    Five,
    /// 6
    Six,
    /// 7
    Seven,
    /// 8
    Eight,
    /// 9
    Nine,
    /// 10
    Ten,
    /// 11
    Eleven,
    /// 12
    Twelve,
    /// 13
    Thirteen,
    /// 14
    Fourteen,
    /// 15
    Fifteen,
    /// 16
    Sixteen,
    /// 17
    Seventeen,
    /// 18
    Eighteen,
}

impl From<Id> for u8 {
    fn from(id: Id) -> Self {
        match id {
            #[cfg(feature = "stm32f373")]
            Id::Zero => 0,
            Id::One => 1,
            Id::Two => 2,
            Id::Three => 3,
            Id::Four => 4,
            Id::Five => 5,
            Id::Six => 6,
            Id::Seven => 7,
            Id::Eight => 8,
            Id::Nine => 9,
            Id::Ten => 10,
            Id::Eleven => 11,
            Id::Twelve => 12,
            Id::Thirteen => 13,
            Id::Fourteen => 14,
            Id::Fifteen => 15,
            Id::Sixteen => 16,
            Id::Seventeen => 17,
            Id::Eighteen => 18,
        }
    }
}

impl TryFrom<u8> for Id {
    type Error = crate::TryFromIntError;

    fn try_from(value: u8) -> Result<Self, Self::Error> {
        Ok(match value {
            #[cfg(feature = "stm32f373")]
            0 => Id::Zero,
            1 => Id::One,
            2 => Id::Two,
            3 => Id::Three,
            4 => Id::Four,
            5 => Id::Five,
            6 => Id::Six,
            7 => Id::Seven,
            8 => Id::Eight,
            9 => Id::Nine,
            10 => Id::Ten,
            11 => Id::Eleven,
            12 => Id::Twelve,
            13 => Id::Thirteen,
            14 => Id::Fourteen,
            15 => Id::Fifteen,
            16 => Id::Sixteen,
            17 => Id::Seventeen,
            18 => Id::Eighteen,
            _ => return Err(crate::TryFromIntError),
        })
    }
}

// impl<ADC, Pin> From<&Pin> for Id
// where
//     Pin: Channel<ADC, ID = Id>,
//     ADC: super::Instance,
// {
//     fn from(_: &Pin) -> Self {
//         todo!()
//     }
// }

// Generated by codegen/tools/adc_channel.py with slight manual adjustments.
cfg_if::cfg_if! {
    if #[cfg(any(feature = "stm32f301x6", feature = "stm32f301x8"))] {
        channel!([
            (PA0, [(ADC1, Id::One)]),
            (PA1, [(ADC1, Id::Two)]),
            (PA2, [(ADC1, Id::Three)]),
            (PA3, [(ADC1, Id::Four)]),
            (PA4, [(ADC1, Id::Five)]),
            (PA6, [(ADC1, Id::Ten)]),
            (PA7, [(ADC1, Id::Fifteen)]),
            (PB0, [(ADC1, Id::Eleven)]),
            (PB11, [(ADC1, Id::Fourteen)]),
            (PB13, [(ADC1, Id::Thirteen)]),
            (PB1, [(ADC1, Id::Twelve)]),
            (PC0, [(ADC1, Id::Six)]),
            (PC1, [(ADC1, Id::Seven)]),
            (PC2, [(ADC1, Id::Eight)]),
            (PC3, [(ADC1, Id::Nine)]),
        ]);
    } else if #[cfg(any(feature = "stm32f302x6", feature = "stm32f302x8"))] {
        channel!([
            (PA0, [(ADC1, Id::One)]),
            (PA1, [(ADC1, Id::Two)]),
            (PA2, [(ADC1, Id::Three)]),
            (PA3, [(ADC1, Id::Four)]),
            (PA4, [(ADC1, Id::Five)]),
            (PA6, [(ADC1, Id::Ten)]),
            (PA7, [(ADC1, Id::Fifteen)]),
            (PB0, [(ADC1, Id::Eleven)]),
            (PB11, [(ADC1, Id::Fourteen)]),
            (PB13, [(ADC1, Id::Thirteen)]),
            (PB1, [(ADC1, Id::Twelve)]),
            (PC0, [(ADC1, Id::Six)]),
            (PC1, [(ADC1, Id::Seven)]),
            (PC2, [(ADC1, Id::Eight)]),
            (PC3, [(ADC1, Id::Nine)]),
        ]);
    } else if #[cfg(any(feature = "stm32f303x6", feature = "stm32f303x8"))] {
        channel!([
            (PA0, [(ADC1, Id::One)]),
            (PA1, [(ADC1, Id::Two)]),
            (PA2, [(ADC1, Id::Three)]),
            (PA3, [(ADC1, Id::Four)]),
            (PA4, [(ADC2, Id::One)]),
            (PA5, [(ADC2, Id::Two)]),
            (PA6, [(ADC2, Id::Three)]),
            (PA7, [(ADC2, Id::Four)]),
            (PB0, [(ADC1, Id::Eleven)]),
            (PB12, [(ADC2, Id::Thirteen)]),
            (PB13, [(ADC1, Id::Thirteen)]),
            (PB14, [(ADC2, Id::Fourteen)]),
            (PB15, [(ADC2, Id::Fifteen)]),
            (PB1, [(ADC1, Id::Twelve)]),
            (PB2, [(ADC2, Id::Twelve)]),
            (PC3, [(ADC1, Id::Nine), (ADC2, Id::Nine)]),
            (PC4, [(ADC2, Id::Five)]),
            (PC5, [(ADC2, Id::Eleven)]),
        ]);
    } else if #[cfg(any(feature = "stm32f302xb", feature = "stm32f302xc"))] {
        channel!([
            (PA0, [(ADC1, Id::One)]),
            (PA1, [(ADC1, Id::Two)]),
            (PA2, [(ADC1, Id::Three)]),
            (PA3, [(ADC1, Id::Four)]),
            (PA4, [(ADC2, Id::One)]),
            (PA5, [(ADC2, Id::Two)]),
            (PA6, [(ADC2, Id::Three)]),
            (PA7, [(ADC2, Id::Four)]),
            (PB2, [(ADC2, Id::Twelve)]),
            (PC0, [(ADC1, Id::Six), (ADC2, Id::Six)]),
            (PC1, [(ADC1, Id::Seven), (ADC2, Id::Seven)]),
            (PC2, [(ADC1, Id::Eight), (ADC2, Id::Eight)]),
            (PC3, [(ADC1, Id::Nine), (ADC2, Id::Nine)]),
            (PC4, [(ADC2, Id::Five)]),
            (PC5, [(ADC2, Id::Eleven)]),
            (PF4, [(ADC1, Id::Five)]),
        ]);
    } else if #[cfg(any(feature = "stm32f303xb", feature = "stm32f303xc"))] {
        channel!([
            (PA0, [(ADC1, Id::One)]),
            (PA1, [(ADC1, Id::Two)]),
            (PA2, [(ADC1, Id::Three)]),
            (PA3, [(ADC1, Id::Four)]),
            (PA4, [(ADC2, Id::One)]),
            (PA5, [(ADC2, Id::Two)]),
            (PA6, [(ADC2, Id::Three)]),
            (PA7, [(ADC2, Id::Four)]),
            (PB0, [(ADC3, Id::Twelve)]),
            (PB12, [(ADC4, Id::Three)]),
            (PB13, [(ADC3, Id::Five)]),
            (PB14, [(ADC4, Id::Four)]),
            (PB15, [(ADC4, Id::Five)]),
            (PB1, [(ADC3, Id::One)]),
            (PB2, [(ADC2, Id::Twelve)]),
            (PC0, [(ADC1, Id::Six), (ADC2, Id::Six)]),
            (PC1, [(ADC1, Id::Seven), (ADC2, Id::Seven)]),
            (PC2, [(ADC1, Id::Eight), (ADC2, Id::Eight)]),
            (PC3, [(ADC1, Id::Nine), (ADC2, Id::Nine)]),
            (PC4, [(ADC2, Id::Five)]),
            (PC5, [(ADC2, Id::Eleven)]),
            (PF4, [(ADC1, Id::Five)]),
        ]);
    } else if #[cfg(any(feature = "stm32f302xd", feature = "stm32f302xe"))] {
        channel!([
            (PA0, [(ADC1, Id::One)]),
            (PA1, [(ADC1, Id::Two)]),
            (PA2, [(ADC1, Id::Three)]),
            (PA3, [(ADC1, Id::Four)]),
            (PA4, [(ADC2, Id::One)]),
            (PA5, [(ADC2, Id::Two)]),
            (PA6, [(ADC2, Id::Three)]),
            (PA7, [(ADC2, Id::Four)]),
            (PB11, [(ADC1, Id::Fourteen), (ADC2, Id::Fourteen)]),
            (PB2, [(ADC2, Id::Twelve)]),
            (PC0, [(ADC1, Id::Six), (ADC2, Id::Six)]),
            (PC1, [(ADC1, Id::Seven), (ADC2, Id::Seven)]),
            (PC2, [(ADC1, Id::Eight), (ADC2, Id::Eight)]),
            (PC3, [(ADC1, Id::Nine), (ADC2, Id::Nine)]),
            (PC4, [(ADC2, Id::Five)]),
            (PC5, [(ADC2, Id::Eleven)]),
            (PF2, [(ADC1, Id::Ten), (ADC2, Id::Ten)]),
            (PF4, [(ADC1, Id::Five)]),
        ]);
    } else if #[cfg(any(feature = "stm32f303xd", feature = "stm32f303xe"))] {
        channel!([
            (PA0, [(ADC1, Id::One)]),
            (PA1, [(ADC1, Id::Two)]),
            (PA2, [(ADC1, Id::Three)]),
            (PA3, [(ADC1, Id::Four)]),
            (PA4, [(ADC2, Id::One)]),
            (PA5, [(ADC2, Id::Two)]),
            (PA6, [(ADC2, Id::Three)]),
            (PA7, [(ADC2, Id::Four)]),
            (PB0, [(ADC3, Id::Twelve)]),
            (PB11, [(ADC1, Id::Fourteen), (ADC2, Id::Fourteen)]),
            (PB12, [(ADC4, Id::Three)]),
            (PB13, [(ADC3, Id::Five)]),
            (PB14, [(ADC4, Id::Four)]),
            (PB15, [(ADC4, Id::Five)]),
            (PB1, [(ADC3, Id::One)]),
            (PB2, [(ADC2, Id::Twelve)]),
            (PC0, [(ADC1, Id::Six), (ADC2, Id::Six)]),
            (PC1, [(ADC1, Id::Seven), (ADC2, Id::Seven)]),
            (PC2, [(ADC1, Id::Eight), (ADC2, Id::Eight)]),
            (PC3, [(ADC1, Id::Nine), (ADC2, Id::Nine)]),
            (PC4, [(ADC2, Id::Five)]),
            (PC5, [(ADC2, Id::Eleven)]),
            (PD10, [(ADC3, Id::Seven), (ADC4, Id::Seven)]),
            (PD11, [(ADC3, Id::Eight), (ADC4, Id::Eight)]),
            (PD12, [(ADC3, Id::Nine), (ADC4, Id::Nine)]),
            (PD13, [(ADC3, Id::Ten), (ADC4, Id::Ten)]),
            (PD14, [(ADC3, Id::Eleven), (ADC4, Id::Eleven)]),
            (PD9, [(ADC4, Id::Thirteen)]),
            (PE9, [(ADC3, Id::Two)]),
            (PE10, [(ADC3, Id::Fourteen)]),
            (PE11, [(ADC3, Id::Fifteen)]),
            (PE12, [(ADC3, Id::Sixteen)]),
            (PE7, [(ADC3, Id::Thirteen)]),
            (PE8, [(ADC3, Id::Six), (ADC4, Id::Six)]),
            (PF2, [(ADC1, Id::Ten), (ADC2, Id::Ten)]),
        ]);
    } else if #[cfg(feature = "stm32f328")] {
        channel!([
            (PA0, [(ADC1, Id::One)]),
            (PA1, [(ADC1, Id::Two)]),
            (PA2, [(ADC1, Id::Three)]),
            (PA3, [(ADC1, Id::Four)]),
            (PA4, [(ADC2, Id::One)]),
            (PA5, [(ADC2, Id::Two)]),
            (PA6, [(ADC2, Id::Three)]),
            (PA7, [(ADC2, Id::Four)]),
            (PB0, [(ADC1, Id::Eleven)]),
            (PB12, [(ADC2, Id::Thirteen)]),
            (PB13, [(ADC1, Id::Thirteen)]),
            (PB14, [(ADC2, Id::Fourteen)]),
            (PB15, [(ADC2, Id::Fifteen)]),
            (PB1, [(ADC1, Id::Twelve)]),
        ]);
    } else if #[cfg(feature = "stm32f358")] {
        channel!([
            (PA0, [(ADC1, Id::One)]),
            (PA1, [(ADC1, Id::Two)]),
            (PA2, [(ADC1, Id::Three)]),
            (PA3, [(ADC1, Id::Four)]),
            (PA4, [(ADC2, Id::One)]),
            (PA5, [(ADC2, Id::Two)]),
            (PA6, [(ADC2, Id::Three)]),
            (PA7, [(ADC2, Id::Four)]),
            (PB0, [(ADC3, Id::Twelve)]),
            (PB12, [(ADC4, Id::Three)]),
            (PB13, [(ADC3, Id::Five)]),
            (PB14, [(ADC4, Id::Four)]),
            (PB15, [(ADC4, Id::Five)]),
            (PB1, [(ADC3, Id::One)]),
            (PC0, [(ADC1, Id::Six), (ADC2, Id::Six)]),
            (PC1, [(ADC1, Id::Seven), (ADC2, Id::Seven)]),
            (PC2, [(ADC1, Id::Eight), (ADC2, Id::Eight)]),
            (PC3, [(ADC1, Id::Nine), (ADC2, Id::Nine)]),
            (PC4, [(ADC2, Id::Five)]),
            (PC5, [(ADC2, Id::Eleven)]),
            (PF4, [(ADC1, Id::Five)]),
        ]);
    } else if #[cfg(feature = "stm32f398")] {
        channel!([
            (PA0, [(ADC1, Id::One)]),
            (PA1, [(ADC1, Id::Two)]),
            (PA2, [(ADC1, Id::Three)]),
            (PA3, [(ADC1, Id::Four)]),
            (PA4, [(ADC2, Id::One)]),
            (PA5, [(ADC2, Id::Two)]),
            (PA6, [(ADC2, Id::Three)]),
            (PA7, [(ADC2, Id::Four)]),
            (PB0, [(ADC3, Id::Twelve)]),
            (PB11, [(ADC1, Id::Fourteen), (ADC2, Id::Fourteen)]),
            (PB12, [(ADC4, Id::Three)]),
            (PB13, [(ADC3, Id::Five)]),
            (PB14, [(ADC4, Id::Four)]),
            (PB15, [(ADC4, Id::Five)]),
            (PB1, [(ADC3, Id::One)]),
            (PC0, [(ADC1, Id::Six), (ADC2, Id::Six)]),
            (PC1, [(ADC1, Id::Seven), (ADC2, Id::Seven)]),
            (PC2, [(ADC1, Id::Eight), (ADC2, Id::Eight)]),
            (PC3, [(ADC1, Id::Nine), (ADC2, Id::Nine)]),
            (PC4, [(ADC2, Id::Five)]),
            (PC5, [(ADC2, Id::Eleven)]),
            (PD10, [(ADC3, Id::Seven), (ADC4, Id::Seven)]),
            (PD11, [(ADC3, Id::Eight), (ADC4, Id::Eight)]),
            (PD12, [(ADC3, Id::Nine), (ADC4, Id::Nine)]),
            (PD13, [(ADC3, Id::Ten), (ADC4, Id::Ten)]),
            (PD14, [(ADC3, Id::Eleven), (ADC4, Id::Eleven)]),
            (PD8, [(ADC4, Id::Twelve)]),
            (PD9, [(ADC4, Id::Thirteen)]),
            (PE10, [(ADC3, Id::Fourteen)]),
            (PE11, [(ADC3, Id::Fifteen)]),
            (PE12, [(ADC3, Id::Sixteen)]),
            (PE13, [(ADC3, Id::Three)]),
            (PE14, [(ADC4, Id::One)]),
            (PE15, [(ADC4, Id::Two)]),
            (PE7, [(ADC3, Id::Thirteen)]),
            (PE8, [(ADC3, Id::Six), (ADC4, Id::Six)]),
            (PE9, [(ADC3, Id::Two)]),
            (PF2, [(ADC1, Id::Ten), (ADC2, Id::Ten)]),
        ]);
    } else if #[cfg(feature = "stm32f373")] {
        channel!([
            (PA0, [(ADC1, Id::Zero)]),
            (PA1, [(ADC1, Id::One)]),
            (PA2, [(ADC1, Id::Two)]),
            (PA3, [(ADC1, Id::Three)]),
            (PA4, [(ADC1, Id::Four)]),
            (PA5, [(ADC1, Id::Five)]),
            (PA6, [(ADC1, Id::Six)]),
            (PB0, [(ADC1, Id::Eight)]),
            (PB1, [(ADC1, Id::Nine)]),
        ]);
    } else if #[cfg(feature = "stm32f334")] {
        channel!([
            (PA0, [(ADC1, Id::One)]),
            (PA1, [(ADC1, Id::Two)]),
            (PA2, [(ADC1, Id::Three)]),
            (PA3, [(ADC1, Id::Four)]),
            (PA4, [(ADC2, Id::One)]),
            (PA5, [(ADC2, Id::Two)]),
            (PA6, [(ADC2, Id::Three)]),
            (PA7, [(ADC2, Id::Four)]),
            (PB0, [(ADC1, Id::Eleven)]),
            (PB12, [(ADC2, Id::Thirteen)]),
            (PB13, [(ADC1, Id::Thirteen)]),
            (PB14, [(ADC2, Id::Fourteen)]),
            (PB15, [(ADC2, Id::Fifteen)]),
            (PB1, [(ADC1, Id::Twelve)]),
            (PB2, [(ADC2, Id::Twelve)]),
            (PC3, [(ADC1, Id::Nine), (ADC2, Id::Nine)]),
            (PC4, [(ADC2, Id::Five)]),
            (PC5, [(ADC2, Id::Eleven)]),
        ]);
    }
}
